package com.netflexitysolutions.amazonws.sdb.orm.internal.operations;

import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.netflexitysolutions.amazonws.sdb.Item;
import com.netflexitysolutions.amazonws.sdb.orm.SimpleDBSession;
import com.netflexitysolutions.amazonws.sdb.orm.filter.Predicate;
import com.netflexitysolutions.amazonws.sdb.orm.internal.util.AmazonSDBDataUtils;
import com.netflexitysolutions.amazonws.sdb.orm.internal.util.QueryUtils;
import com.netflexitysolutions.amazonws.sdb.orm.internal.util.StringConstants;
import com.netflexitysolutions.amazonws.sdb.orm.metadata.AttributeMetadata;
import com.netflexitysolutions.amazonws.sdb.orm.metadata.ItemMetadata;

public class Count<T>{

	private static Log logger = LogFactory.getLog(Count.class.getName());
	
	private SimpleDBSession session;
	private Predicate<T> predicate;
	
	/**
	 * @param session
	 * @param predicate
	 */
	public Count(SimpleDBSession session, Predicate<T> predicate) {
		this.session = session;
		this.predicate = predicate;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.concurrent.Callable#call()
	 */
	public Integer call() throws Exception {
		Integer count = null;
		
		// Get query.
		String query = getQuery();
		
        logger.debug("About to execute select query:" + query);
        
        Iterator<List<Item>> itemIterator = session.getFactory().getDataSource().select(query);
        while (itemIterator.hasNext()) {
			List<Item> list = (List<Item>) itemIterator.next();
			for (Item item : list) {
				if(!item.getAttributes().isEmpty()){
					String value = item.getAttributes().get(0).getValue();
					count = AmazonSDBDataUtils.decodeRealNumberRange(value, AttributeMetadata.OFFSET_VALUE).intValue();
					break;
				}
			}
		}
        
        return count;
	}
	
	/**
	 * @return
	 */
	public String getQuery(){
		// Get item metadata.
		ItemMetadata itemMetadata = session.getMetadata(predicate.getType());
		
		// Get where clause.
		String where = predicate.toSelect();
		
        // Construct query.
        StringBuffer selectQuery = new StringBuffer(1024);
        selectQuery.append(QueryUtils.SELECT_COUNT_ALL_FROM).append(StringConstants.TICK).append(itemMetadata.getDomainName()).append(StringConstants.TICK);
        if(StringUtils.isNotBlank(where)){
        	selectQuery.append(QueryUtils.WHERE).append(where);
        }
        
        // Handle logical name.
        if(StringUtils.isNotBlank(itemMetadata.getLogicalName())){
        	if(StringUtils.isBlank(where)){
        		selectQuery.append(QueryUtils.WHERE);
        	}
        	else{
        		selectQuery.append(QueryUtils.AND);
        	}
        	selectQuery.append(StringConstants.TICK).append(itemMetadata.getLogicalNameColumnName()).append(StringConstants.TICK)
        	.append(StringConstants.EQ)
        	.append(StringConstants.DOUBLE_QUOTE).append(itemMetadata.getLogicalName()).append(StringConstants.DOUBLE_QUOTE);
        }
        
        return selectQuery.toString();
	}
}
